

/* 获取设备列表 */
const getDevices = () => {
  return new Promise((resolve, reject) => {
    resolve(navigator.mediaDevices?.enumerateDevices())
  })
}

/* 创建PeerConnection */
const getPeerConnection = (onicecandidate: ((this: RTCPeerConnection, ev: RTCPeerConnectionIceEvent) => any) | null,
    ontrack: ((this: RTCPeerConnection, ev: RTCTrackEvent) => any) | null,
    onicegatheringcomplete: (() => any)) => {
  var pc = new RTCPeerConnection(undefined);
  pc.onicecandidate = onicecandidate;
  pc.ontrack = ontrack;
  pc.onicegatheringstatechange = () => {
    if (pc.iceGatheringState === 'complete') {
      onicegatheringcomplete();
    }
  };
  return pc;
}

/* 绑定candidate */
const addIceCandidate = (pc: RTCPeerConnection, candidate: RTCIceCandidate) => {
  return new Promise((resolve, reject) => {
    if (pc) {
      pc.addIceCandidate(new RTCIceCandidate(candidate))
        .then(resolve)
        .catch(reject);
    } else {
      reject('peerconnection is null.');
    }
  })
}

/* 绑定音视频流到PeerConnection */
const addTracks = (pc: RTCPeerConnection, stream: MediaStream) => {
  if (pc && stream) {
    stream.getTracks().forEach(
      (track) => {
        pc.addTrack(track, stream);
      });
  }
}

const createOffer = (pc: RTCPeerConnection, mediaConstraints: RTCOfferOptions) => {
  return new Promise(async (resolve, reject) => {
    if (pc) {
      // TODO 官网建议，createOffer 的时候，不要传参数
      const desc = await pc.createOffer(mediaConstraints)
      await pc.setLocalDescription(desc);
      resolve(desc);
    } else {
      reject('peerconnection is null.');
    }
  })
}

/* 创建应答 */
const createAnswer = (pc: RTCPeerConnection, remoteSdp: RTCSessionDescription, mediaConstraints: RTCOfferOptions) => {
  return new Promise(async (resolve, reject) => {
    if (pc) {
      var remoteDesc = new RTCSessionDescription(remoteSdp);
      //remoteDesc.sdp = updateBandwidthRestriction(remoteDesc.sdp, bindwidth);
      await pc.setRemoteDescription(remoteDesc)
      const localDesc = await pc.createAnswer(mediaConstraints);
      await pc.setLocalDescription(localDesc)
      resolve(localDesc)
    } else {
      reject('peerconnection is null.');
    }
  })
}

/* 接收应答 */
const receiveAnswer = (pc: RTCPeerConnection, remoteSdp: RTCSessionDescription,) => {
  return new Promise((resolve, reject) => {
    if (pc) {
      var remoteDesc = new RTCSessionDescription(remoteSdp);
      //remoteDesc.sdp = updateBandwidthRestriction(remoteDesc.sdp, bindwidth);
      pc.setRemoteDescription(remoteDesc).then(resolve).catch(reject);
    } else {
      reject('peerconnection is null.');
    }
  })
}

/* 关闭PeerConnection */
const closePC = (pc: RTCPeerConnection) => {
  if (pc) {
    //释放PeerConnection资源
    pc.close();
    pc.onicecandidate = null;
    pc.ontrack = null;
    // pc = null; // TODO here
  }
}

const mute = (stream: MediaStream, ismute: boolean) => {
  return new Promise((resolve, reject) => {
    if (stream) {
      stream.getAudioTracks().forEach(
        (track) => {
          track.enabled = !ismute;
        });
      resolve(true)
    } else {
      reject('[mute] mediatream is null.');
    }
  })
}
const muteVideo = (stream: MediaStream, ismute: boolean) => {
  return new Promise((resolve, reject) => {
    if (stream) {
      stream.getVideoTracks().forEach(
        (track) => {
          track.enabled = !ismute;
        });
      resolve(true)
    } else {
      reject('[muteVideo] mediatream is null.');
    }
  })
}

  // // Find the line in sdpLines that starts with |prefix|, and, if specified,
  // // contains |substr| (case-insensitive search).
  // private findLine = (sdpLines, prefix, substr) => {
  //   return this.findLineInRange(sdpLines, 0, -1, prefix, substr);
  // }

  // // Find the line in sdpLines[startLine...endLine - 1] that starts with |prefix|
  // // and, if specified, contains |substr| (case-insensitive search).
  // private findLineInRange = (sdpLines, startLine, endLine, prefix, substr) => {
  //   var realEndLine = endLine !== -1 ? endLine : sdpLines.length;
  //   for (var i = startLine; i < realEndLine; ++i) {
  //     if (sdpLines[i].indexOf(prefix) === 0) {
  //       if (!substr ||
  //         sdpLines[i].toLowerCase().indexOf(substr.toLowerCase()) !== -1) {
  //         return i;
  //       }
  //     }
  //   }
  //   return null;
  // }

  // // Gets the codec payload type from an a=rtpmap:X line.
  // private getCodecPayloadType = (sdpLine) => {
  //   var pattern = new RegExp('a=rtpmap:(\\d+) \\w+\\/\\d+');
  //   var result = sdpLine.match(pattern);
  //   return (result && result.length === 2) ? result[1] : null;
  // }

  // /* 设置码率 */
  // private setVideoBitrate = (sdp, bitrate) => {
  //   var xgoogle_min_bitrate = bitrate;
  //   var xgoogle_max_bitrate = bitrate;

  //   var sdpLines = sdp.split('\r\n');

  //   // H264
  //   var h264Index = this.findLine(sdpLines, 'a=rtpmap', 'H264/90000');
  //   var h264Payload;
  //   if (h264Index) {
  //     h264Payload = getCodecPayloadType(sdpLines[h264Index]);
  //   }

  //   if (!h264Payload) {
  //     return sdp;
  //   }

  //   var appendrtxNext = '\r\n';
  //   appendrtxNext += 'a=fmtp:' + h264Payload + ' x-google-min-bitrate=' + (xgoogle_min_bitrate || '228') + '; x-google-max-bitrate=' + (xgoogle_max_bitrate || '228');
  //   sdpLines[h264Index] = sdpLines[h264Index].concat(appendrtxNext);
  //   sdp = sdpLines.join('\r\n');

  //   return sdp;
  // }

  // /* 设置带宽限制 */
  // private updateBandwidthRestriction = (sdp, bandwidth) => {
  //   if (!bandwidth || bandwidth == 'unlimited') {
  //     //无限制
  //     return sdp.replace(/b=AS:.*\r\n/, '').replace(/b=TIAS:.*\r\n/, '');
  //   } else {
  //     var modifier = 'AS';
  //     if (sdp.indexOf('b=' + modifier + ':') === -1) {
  //       // insert b= after c= line.
  //       // sdp = sdp.replace(/c=IN (.*)\r\n/,
  //       //     'c=IN $1\r\nb=' + modifier + ':' + bandwidth + '\r\n');
  //       sdp = sdp.replace(/a=mid:video\r\n/g,
  //         'a=mid:video\r\nb=' + modifier + ':' + bandwidth + '\r\n');
  //     } else {
  //       sdp = sdp.replace(new RegExp('b=' + modifier + ':.*\r\n'),
  //         'b=' + modifier + ':' + bandwidth + '\r\n');
  //     }
  //     return sdp;
  //   }
  // }